home *** CD-ROM | disk | FTP | other *** search
/ Aminet 4 / Aminet 4 - November 1994.iso / aminet / dev / gui / muibuilderv11.lha / muibuilder / mb / e / Mac2E.lha / Mac2E / Sources / PreMac2E.e < prev    next >
Text File  |  1994-03-10  |  27KB  |  725 lines

  1. OPT OSVERSION=37
  2.  
  3. /* Traitements des erreurs */
  4. /*SF*/
  5. ENUM    OUT_OF_MEMORY,ARGS_ERROR,IO_ERROR,FILE_END_REACHED,INCORRECT_DEFINE,WRONG_MACRO_NAME,
  6.         WRONG_MACRO_ARGS,WRONG_MACRO_BODY,WRONG_MACRO_USE
  7.  
  8. RAISE   OUT_OF_MEMORY   IF New()=NIL,
  9.         OUT_OF_MEMORY   IF List()=NIL,
  10.         OUT_OF_MEMORY   IF String()=NIL,
  11.         ARGS_ERROR      IF ReadArgs()=NIL,
  12.         IO_ERROR        IF Open()=NIL
  13. /*EF*/
  14.  
  15. /* Definition des constantes */
  16. /*SF*/
  17. CONST LONG_DEF_MACRO=4
  18. CONST LONG_MORCEAU_CORPS=6
  19. /*EF*/
  20.  
  21. /* Definition des objets */
  22. /*SF*/
  23. OBJECT ident_hash
  24.     ident   :LONG
  25.     hash    :LONG
  26. ENDOBJECT
  27.  
  28. OBJECT def_macro
  29.     nom         :LONG
  30.     nbre_args   :LONG
  31.     corps       :LONG
  32.     analysee    :LONG
  33. ENDOBJECT
  34.  
  35. OBJECT entree_table
  36.     liste_macros:LONG
  37.     nbre_macros :LONG
  38. ENDOBJECT
  39.  
  40. OBJECT morceau_chaine
  41.     macro           :LONG
  42.     ptr_macro       :LONG   /* si c'est une macro */
  43.     parametres      :LONG
  44.     chaine_traite   :LONG
  45.     ptr_texte       :LONG   /* si c'est une macro */
  46.     longueur        :LONG
  47. ENDOBJECT
  48. /*EF*/
  49.  
  50. /* Definition des variables globales */
  51. /*SF*/
  52. DEF table_macros[256]:ARRAY OF entree_table
  53. DEF num_ligne
  54. /*EF*/
  55.  
  56. /**********************/
  57. /* Corps du programme */
  58. /**********************/
  59. PROC main() HANDLE
  60. /*SF*/
  61.     DEF rdargs,arguments:PTR TO LONG
  62.     DEF version,i
  63.  
  64.     Vprintf('         \c1;33;40\cPreMac2E\c0;31;40\c v1.0\n',[$9B,$6D,$9B,$6D])
  65.     PutStr('Copyright © 1994, Lionel Vintenat\n')
  66.     Vprintf('\c1;32;40\c---------------------------------\c0;31;40\c\n',[$9B,$6D,$9B,$6D])
  67.     version:='$VER: PreMac2E 1.0 (10.3.94)'
  68.  
  69.     arguments:=[NIL,NIL,0,0]
  70.     rdargs:=ReadArgs('FROM/A,TO/A,VER=VERBOSE/S,KS=KEEPSPACES/S',arguments,NIL)
  71.  
  72.     FOR i:=0 TO 255
  73.         table_macros[i].liste_macros:=NIL
  74.         table_macros[i].nbre_macros:=0
  75.     ENDFOR
  76.  
  77.     PutStr('Analysing macro file...\n')
  78.     analyser_fichier_macros(arguments[0],arguments[3])
  79.     PutStr('Replacing macro calls inside macro bodies...\n')
  80.     pre_analyser(arguments[2])
  81.     PutStr('Writing pre-analyzed macro file...\n')
  82.     ecrire_fichier_macros_analyse(arguments[1])
  83.  
  84.     FreeArgs(rdargs)
  85.  
  86. EXCEPT
  87.     SELECT exception
  88.         CASE ARGS_ERROR
  89.             PrintFault(IoErr(),NIL)
  90.         CASE OUT_OF_MEMORY
  91.             PutStr('Out of memory !\n')
  92.         CASE IO_ERROR
  93.             PrintFault(IoErr(),NIL)
  94.         CASE FILE_END_REACHED
  95.             Vprintf('Source file ends in the middle of a macro definition in line \d !\n',[num_ligne])
  96.         CASE INCORRECT_DEFINE
  97.             Vprintf('Missing space or tabulation after #define in line \d !\n',[num_ligne])
  98.         CASE WRONG_MACRO_NAME
  99.             Vprintf('Wrong macro name in line \d !\n',[num_ligne])
  100.         CASE WRONG_MACRO_ARGS
  101.             Vprintf('Error in the declaration of the macro parameters in line \d !\n',[num_ligne])
  102.         CASE WRONG_MACRO_BODY
  103.             Vprintf('Null body found in line \d !\n',[num_ligne])
  104.     ENDSELECT
  105.  
  106.     IF rdargs THEN FreeArgs(rdargs)
  107.  
  108.     CleanUp(100)
  109. ENDPROC
  110. /*EF*/
  111.  
  112. /***************************************************************************/
  113. /* Analyse un fichier ne contenant que des macros pour recuperer celles-ci */
  114. /***************************************************************************/
  115. PROC analyser_fichier_macros(nom_fichier:PTR TO CHAR,garder_espaces)
  116. /*SF*/
  117.     DEF fichier,adr_fichier,fin_fichier,long_fichier
  118.     DEF pointeur_car:PTR TO CHAR
  119.  
  120.     fichier:=Open(nom_fichier,OLDFILE)
  121.     long_fichier:=FileLength(nom_fichier)
  122.     adr_fichier:=New(long_fichier)
  123.     fin_fichier:=adr_fichier+long_fichier
  124.     pointeur_car:=adr_fichier
  125.     Read(fichier,adr_fichier,long_fichier)
  126.     Close(fichier)
  127.     num_ligne:=1 
  128.         /* cherche la chaine #define */
  129.     MOVE.L  pointeur_car,A0
  130.     MOVE.L  fin_fichier,A1
  131.     afm_while0:
  132.         CMPA.L  A1,A0               /* pointeur_car=fin_fichier ? */
  133.         BEQ.W   afm_fin_while
  134.         MOVE.B  (A0)+,D0
  135.     afm_while1:
  136.         CMP.B   #10,D0              /* Char(pointeur_car)=10 ? */
  137.         BNE.B   afm_non_add_ligne
  138.         INC num_ligne
  139.         BRA.B   afm_while0
  140.     afm_non_add_ligne:
  141.         CMP.B   #"#",D0             /* Char(pointeur_car)="#" ? */
  142.         BNE.B   afm_while0
  143.  
  144.         CMPA.L  A1,A0               /* pointeur_car=fin_fichier ? */
  145.         BEQ.W   afm_fin_while
  146.         MOVE.B  (A0)+,D0
  147.         CMP.B   #"d",D0             /* Char(pointeur_car)="d" ? */
  148.         BNE.B   afm_while1
  149.  
  150.         CMPA.L  A1,A0               /* pointeur_car=fin_fichier ? */
  151.         BEQ.W   afm_fin_while
  152.         MOVE.B  (A0)+,D0
  153.         CMP.B   #"e",D0             /* Char(pointeur_car)="e" ? */
  154.         BNE.B   afm_while1
  155.  
  156.         CMPA.L  A1,A0               /* pointeur_car=fin_fichier ? */
  157.         BEQ.W   afm_fin_while
  158.         MOVE.B  (A0)+,D0
  159.         CMP.B   #"f",D0             /* Char(pointeur_car)="f" ? */
  160.         BNE.B   afm_while1
  161.  
  162.         CMPA.L  A1,A0               /* pointeur_car=fin_fichier ? */
  163.         BEQ.B   afm_fin_while
  164.         MOVE.B  (A0)+,D0
  165.         CMP.B   #"i",D0             /* Char(pointeur_car)="i" ? */
  166.         BNE.B   afm_while1
  167.  
  168.         CMPA.L  A1,A0               /* pointeur_car=fin_fichier ? */
  169.         BEQ.B   afm_fin_while
  170.         MOVE.B  (A0)+,D0
  171.         CMP.B   #"n",D0             /* Char(pointeur_car)="n" ? */
  172.         BNE.B   afm_while1
  173.  
  174.         CMPA.L  A1,A0               /* pointeur_car=fin_fichier ? */
  175.         BEQ.B   afm_fin_while
  176.         MOVE.B  (A0)+,D0
  177.         CMP.B   #"e",D0             /* Char(pointeur_car)="e" ? */
  178.         BNE.B   afm_while1
  179.  
  180.         CMPA.L  A1,A0               /* pointeur_car=fin_fichier ? */
  181.         BEQ.B   erreur_define
  182.         MOVE.B  (A0)+,D0
  183.         CMP.B   #" ",D0             /* Char(pointeur_car)=" " ? */
  184.         BEQ.B   define_trouve
  185.         CMP.B   #9,D0               /* Char(pointeur_car)=9 ? */
  186.         BEQ.W   define_trouve
  187.     erreur_define:
  188.         Raise(INCORRECT_DEFINE)
  189.     define_trouve:
  190.         MOVE.L  A0,pointeur_car
  191.         pointeur_car:=analyser_macro(pointeur_car,fin_fichier,garder_espaces)
  192.         MOVE.L  pointeur_car,A0
  193.         MOVE.L  fin_fichier,A1
  194.         BRA.W   afm_while0
  195.     afm_fin_while:
  196.  
  197.     Dispose(adr_fichier)
  198. ENDPROC
  199. /*EF*/
  200.  
  201. /*********************************************************************/
  202. /* Analyse une macro et en extrait les informations la caracterisant */
  203. /*********************************************************************/
  204. PROC analyser_macro(pointeur_car:PTR TO CHAR,fin_fichier,garder_espaces)
  205. /*SF*/
  206.     DEF nom_macro:ident_hash,liste_macros_hash:PTR TO def_macro,parametres
  207.  
  208.     pointeur_car:=eliminer_tab_space(pointeur_car,fin_fichier)
  209.     IF pointeur_car<fin_fichier
  210.         pointeur_car:=chercher_identificateur_hash(pointeur_car,fin_fichier,nom_macro)
  211.         IF nom_macro.ident
  212.             table_macros[nom_macro.hash].nbre_macros:=table_macros[nom_macro.hash].nbre_macros+1
  213.             liste_macros_hash:=table_macros[nom_macro.hash].liste_macros
  214.             liste_macros_hash:=Link(List(LONG_DEF_MACRO),liste_macros_hash)
  215.             table_macros[nom_macro.hash].liste_macros:=liste_macros_hash
  216.             liste_macros_hash.nom:=nom_macro.ident
  217.             liste_macros_hash.analysee:=FALSE
  218.             pointeur_car:=args_macro(pointeur_car,fin_fichier,liste_macros_hash,{parametres})
  219.             pointeur_car:=corps_macro(pointeur_car,fin_fichier,liste_macros_hash,parametres,garder_espaces)
  220.         ELSE
  221.             Raise(WRONG_MACRO_NAME)
  222.         ENDIF
  223.     ELSE
  224.         Raise(FILE_END_REACHED)
  225.     ENDIF
  226. ENDPROC pointeur_car
  227. /*EF*/
  228.  
  229. /**********************************************************************************/
  230. /* Elimine tous les espaces et toutes les tabulations jusqu'au prochain caractere */
  231. /**********************************************************************************/
  232. PROC eliminer_tab_space(pointeur_car:PTR TO CHAR,fin_fichier)
  233. /*SF*/
  234. /* WHILE ((Char(pointeur_car)=" ") OR (Char(pointeur_car)=9)) AND (pointeur_car<fin_fichier) DO INC pointeur_car */
  235.         MOVE.L  pointeur_car,A0
  236.         MOVE.L  fin_fichier,A1
  237.     ets_while:
  238.         CMPA.L  A1,A0           /* pointeur_car=fin_fichier ? */
  239.         BEQ.B   ets_fin_while
  240.         MOVE.B  (A0)+,D0
  241.         CMP.B   #" ",D0         /* Char(pointeur_car)=" " ? */
  242.         BEQ.B   ets_while
  243.         CMP.B   #9,D0           /* Char(pointeur_car)=9 ? */
  244.         BEQ.B   ets_while
  245.         SUBQ.L  #1,A0
  246.     ets_fin_while:
  247.         MOVE.L  A0,pointeur_car
  248. ENDPROC pointeur_car
  249. /*EF*/
  250.  
  251. /********************************************************************************************/
  252. /* Retourne l'identificateur pointe actuellement dans le fichier, avec sa valeur hash-codee */
  253. /********************************************************************************************/
  254. PROC chercher_identificateur_hash(pointeur_car:PTR TO CHAR,fin_fichier,ident_reconnu:PTR TO ident_hash)
  255. /*SF*/
  256.     DEF debut_ident,long_ident,hash
  257.  
  258.     debut_ident:=pointeur_car
  259.     MOVE.L  pointeur_car,A0
  260.     MOVE.L  fin_fichier,A1
  261.     CLR.L   D1
  262. /* WHILE (caractere(Char(pointeur_car))) AND (pointeur_car<fin_fichier) DO INC pointeur_car */
  263.     cih_while:
  264.         CMPA.L  A1,A0           /* pointeur_car=fin_fichier ? */
  265.         BEQ.B   cih_fin_while
  266.         MOVE.B  (A0)+,D0
  267.         ADD.B   D0,D1
  268.         CMP.B   #"_",D0         /* Char(pointeur_car)="_" ? */
  269.         BEQ.B   cih_while
  270.         CMP.B   #"A",D0         /* Char(pointeur_car)E["A".."Z"] ?*/
  271.         BCS.B   cih_non_majuscule
  272.         CMP.B   #"Z",D0
  273.         BLS.B   cih_while
  274.     cih_non_majuscule:
  275.         CMP.B   #"a",D0         /* Char(pointeur_car)E["a".."z"] ?*/
  276.         BCS.B   cih_non_minuscule
  277.         CMP.B   #"z",D0
  278.         BLS.B   cih_while
  279.     cih_non_minuscule:
  280.         CMP.B   #"0",D0         /* Char(pointeur_car)E["0".."9"] ?*/
  281.         BCS.B   cih_non_chiffre
  282.         CMP.B   #"9",D0
  283.         BLS.B   cih_while
  284.     cih_non_chiffre:
  285.         SUBQ.L  #1,A0
  286.         SUB.B   D0,D1
  287.     cih_fin_while:
  288.         MOVE.L  A0,pointeur_car
  289.         MOVE.L  D1,hash
  290.     IF long_ident:=(pointeur_car-debut_ident)
  291.         ident_reconnu.ident:=String(long_ident)
  292.         StrCopy(ident_reconnu.ident,debut_ident,long_ident)
  293.         ident_reconnu.hash:=hash
  294.     ELSE
  295.         ident_reconnu.ident:=NIL
  296.     ENDIF
  297. ENDPROC pointeur_car
  298. /*EF*/
  299.  
  300. /*****************************************************************/
  301. /* Retourne l'identificateur pointe actuellement dans le fichier */
  302. /*****************************************************************/
  303. PROC chercher_identificateur(pointeur_car:PTR TO CHAR,fin_fichier,adr_ident:PTR TO CHAR)
  304. /*SF*/
  305.     DEF debut_ident,long_ident
  306.  
  307.     debut_ident:=pointeur_car
  308.     MOVE.L  pointeur_car,A0
  309.     MOVE.L  fin_fichier,A1
  310. /* WHILE (caractere(Char(pointeur_car))) AND (pointeur_car<fin_fichier) DO INC pointeur_car */
  311.     ci_while:
  312.         CMPA.L  A1,A0           /* pointeur_car=fin_fichier ? */
  313.         BEQ.B   ci_fin_while
  314.         MOVE.B  (A0)+,D0
  315.         CMP.B   #"_",D0         /* Char(pointeur_car)="_" ? */
  316.         BEQ.B   ci_while
  317.         CMP.B   #"A",D0         /* Char(pointeur_car)E["A".."Z"] ?*/
  318.         BCS.B   ci_non_majuscule
  319.         CMP.B   #"Z",D0
  320.         BLS.B   ci_while
  321.     ci_non_majuscule:
  322.         CMP.B   #"a",D0         /* Char(pointeur_car)E["a".."z"] ?*/
  323.         BCS.B   ci_non_minuscule
  324.         CMP.B   #"z",D0
  325.         BLS.B   ci_while
  326.     ci_non_minuscule:
  327.         CMP.B   #"0",D0         /* Char(pointeur_car)E["0".."9"] ?*/
  328.         BCS.B   ci_non_chiffre
  329.         CMP.B   #"9",D0
  330.         BLS.B   ci_while
  331.     ci_non_chiffre:
  332.         SUBQ.L  #1,A0
  333.     ci_fin_while:
  334.         MOVE.L  A0,pointeur_car
  335.     IF long_ident:=(pointeur_car-debut_ident)
  336.         ^adr_ident:=String(long_ident)
  337.         StrCopy(^adr_ident,debut_ident,long_ident)
  338.     ELSE
  339.         ^adr_ident:=NIL
  340.     ENDIF
  341. ENDPROC pointeur_car
  342. /*EF*/
  343.  
  344. /*******************************************/
  345. /* Recupere tous les arguments d'une macro */
  346. /*******************************************/
  347. PROC args_macro(pointeur_car:PTR TO CHAR,fin_fichier,ptr_macro:PTR TO def_macro,adr_liste_params)
  348. /*SF*/
  349.     DEF car,ident_attendu=TRUE,param
  350.  
  351.     ptr_macro.nbre_args:=0
  352.     ^adr_liste_params:=NIL
  353.     IF pointeur_car<fin_fichier
  354.         car:=Char(pointeur_car++)
  355.         IF (car=9) OR (car=" ")
  356.             pointeur_car:=eliminer_tab_space(pointeur_car,fin_fichier)
  357.         ELSEIF car="("
  358.             pointeur_car:=eliminer_tab_space(pointeur_car,fin_fichier)
  359.             WHILE pointeur_car<fin_fichier
  360.                 IF (car:=Char(pointeur_car++))=10 THEN INC num_ligne
  361.                 SELECT car
  362.                     CASE ","
  363.                         IF ident_attendu
  364.                             Raise(WRONG_MACRO_ARGS)
  365.                         ELSE
  366.                             pointeur_car:=eliminer_tab_space(pointeur_car,fin_fichier)
  367.                             ident_attendu:=TRUE
  368.                         ENDIF
  369.                     CASE ")"
  370.                         IF ident_attendu
  371.                             Raise(WRONG_MACRO_ARGS)
  372.                         ELSE
  373.                             pointeur_car:=eliminer_tab_space(pointeur_car,fin_fichier)
  374.                             RETURN pointeur_car
  375.                         ENDIF
  376.                     DEFAULT
  377.                         DEC pointeur_car
  378.                         pointeur_car:=chercher_identificateur(pointeur_car,fin_fichier,{param})
  379.                         IF param
  380.                             ^adr_liste_params:=Link(param,^adr_liste_params)
  381.                             ptr_macro.nbre_args:=ptr_macro.nbre_args+1
  382.                             ident_attendu:=FALSE
  383.                             pointeur_car:=eliminer_tab_space(pointeur_car,fin_fichier)
  384.                         ELSE
  385.                             Raise(WRONG_MACRO_ARGS)
  386.                         ENDIF
  387.                 ENDSELECT
  388.             ENDWHILE
  389.         ELSE
  390.             Raise(WRONG_MACRO_ARGS)
  391.         ENDIF
  392.     ELSE
  393.         Raise(FILE_END_REACHED)
  394.     ENDIF
  395. ENDPROC pointeur_car
  396. /*EF*/
  397.  
  398. /*****************************************************************/
  399. /* Retourne le corps de la macro, ou NIL si pas de corps reconnu */
  400. /*****************************************************************/
  401. PROC corps_macro(pointeur_car:PTR TO CHAR,fin_fichier,ptr_macro:PTR TO def_macro,parametres,garder_espaces)
  402. /*SF*/
  403.     DEF code_arg[1]:STRING,corps_temp[4096]:STRING
  404.     DEF long_corps,car,suite=FALSE,ident,pos
  405.  
  406.     WHILE pointeur_car<fin_fichier
  407.         car:=Char(pointeur_car++)
  408.         SELECT car
  409.             CASE "\"
  410.                 IF suite THEN StrAdd(corps_temp,'\\',1) ELSE suite:=TRUE
  411.             CASE 10
  412.                 INC num_ligne
  413.                 IF suite
  414.                     suite:=FALSE
  415.                     IF garder_espaces=FALSE THEN pointeur_car:=eliminer_tab_space(pointeur_car,fin_fichier)
  416.                 ELSE
  417.                     IF long_corps:=EstrLen(corps_temp)
  418.                         ptr_macro.corps:=String(long_corps)
  419.                         StrCopy(ptr_macro.corps,corps_temp,long_corps)
  420.                         RETURN pointeur_car
  421.                     ELSE
  422.                         DEC num_ligne
  423.                         Raise(WRONG_MACRO_BODY)
  424.                     ENDIF
  425.                 ENDIF
  426.             DEFAULT
  427.                 IF suite
  428.                     StrAdd(corps_temp,'\\',1)
  429.                     suite:=FALSE
  430.                 ENDIF
  431.                 pointeur_car:=chercher_identificateur(pointeur_car--,fin_fichier,{ident})
  432.                 IF ident
  433.                     IF (pos:=est_ce_arg(ident,parametres))<>-1
  434.                         StringF(code_arg,'\c',pos+128)
  435.                         StrAdd(corps_temp,code_arg,1)
  436.                     ELSE
  437.                         StrAdd(corps_temp,ident,ALL)
  438.                     ENDIF
  439.                 ELSE
  440.                     StrAdd(corps_temp,pointeur_car,1)
  441.                     INC pointeur_car
  442.                 ENDIF
  443.         ENDSELECT
  444.     ENDWHILE
  445.     IF long_corps:=EstrLen(corps_temp)
  446.         ptr_macro.corps:=String(long_corps)
  447.         StrCopy(ptr_macro.corps,corps_temp,long_corps)
  448.     ELSE
  449.         Raise(WRONG_MACRO_BODY)
  450.     ENDIF
  451. ENDPROC pointeur_car
  452. /*EF*/
  453.  
  454. /**************************************************************************/
  455. /* Renvoie le numero (0..nbre_args-1) de l'argument de la macro, -1 sinon */
  456. /**************************************************************************/
  457. PROC est_ce_arg(arg,parametres)
  458. /*SF*/
  459.     DEF num_arg=0
  460.  
  461.     WHILE parametres
  462.         IF StrCmp(parametres,arg,ALL)
  463.             RETURN num_arg
  464.         ELSE
  465.             parametres:=Next(parametres)
  466.             INC num_arg
  467.         ENDIF
  468.     ENDWHILE
  469. ENDPROC -1
  470. /*EF*/
  471.  
  472.  
  473. /**********************************************/
  474. /* Dirige la pre-analyse des corps des macros */
  475. /**********************************************/
  476. PROC pre_analyser(verbose)
  477. /*SF*/
  478.     DEF liste_macros_hash:PTR TO def_macro,i
  479.  
  480.     FOR i:=0 TO 255
  481.         liste_macros_hash:=table_macros[i].liste_macros
  482.         WHILE liste_macros_hash
  483.             pre_analyser_macro(liste_macros_hash,verbose)
  484.             liste_macros_hash:=Next(liste_macros_hash)
  485.         ENDWHILE
  486.     ENDFOR
  487. ENDPROC
  488. /*EF*/
  489.  
  490. /**********************************************************************/
  491. /* Effectue tous les remplacements possibles dans le corps des macros */
  492. /**********************************************************************/
  493. PROC pre_analyser_macro(ptr_macro:PTR TO def_macro,verbose)
  494. /*SF*/
  495.  
  496.     IF ptr_macro.analysee=FALSE
  497.         IF verbose THEN Vprintf('\t--> \s\n',[ptr_macro.nom])
  498.         ptr_macro.corps:=traiter_chaine(ptr_macro.corps,verbose)
  499.         ptr_macro.analysee:=TRUE
  500.     ENDIF
  501. ENDPROC
  502. /*EF*/
  503.  
  504. /****************************************************************************************/
  505. /* Remplace dans chaine_avant toutes les macros par leur corps et retourne chaine_apres */
  506. /****************************************************************************************/
  507. PROC traiter_chaine(chaine_avant:PTR TO CHAR,verbose)
  508. /*SF*/
  509.     DEF chaine_apres:PTR TO CHAR,long_chaine_apres=0,fin_chaine_avant
  510.     DEF nom_ident:ident_hash,ptr_macro:PTR TO def_macro
  511.     DEF deb_morceau,morceaux:PTR TO morceau_chaine,morceaux_temp:PTR TO morceau_chaine
  512.     DEF morceau:PTR TO morceau_chaine,parametres:PTR TO LONG
  513.     DEF pointeur_car,pointeur_car_temp,long_temp,i
  514.  
  515.     fin_chaine_avant:=chaine_avant+EstrLen(chaine_avant)
  516.     morceaux:=NIL
  517.     pointeur_car:=chaine_avant
  518.     deb_morceau:=chaine_avant
  519.     WHILE pointeur_car<fin_chaine_avant
  520.         pointeur_car_temp:=pointeur_car
  521.         pointeur_car:=chercher_identificateur_hash(pointeur_car,fin_chaine_avant,nom_ident)
  522.         IF nom_ident.ident
  523.             IF ptr_macro:=est_ce_macro(nom_ident.ident,nom_ident.hash)
  524.                 IF long_temp:=(pointeur_car_temp-deb_morceau)
  525.                     morceaux:=Link(List(LONG_MORCEAU_CORPS),morceaux)
  526.                     morceaux.macro:=FALSE
  527.                     morceaux.ptr_texte:=deb_morceau
  528.                     morceaux.longueur:=long_temp
  529.                     long_chaine_apres:=long_chaine_apres+morceaux.longueur
  530.                 ENDIF
  531.                 morceaux:=Link(List(LONG_MORCEAU_CORPS),morceaux)
  532.                 morceaux.macro:=TRUE
  533.                 morceaux.ptr_macro:=ptr_macro
  534.                 IF ptr_macro.nbre_args
  535.                     morceaux.parametres:=List(ptr_macro.nbre_args)
  536.                     pointeur_car:=recuperer_args_macro(pointeur_car,fin_chaine_avant,ptr_macro,morceaux.parametres)
  537.                 ELSE
  538.                     IF (Char(pointeur_car)="(") AND (pointeur_car<>fin_chaine_avant)
  539.                         Vprintf('Wrong number of args in \s call !\n',[ptr_macro.nom])
  540.                         Raise(WRONG_MACRO_USE)
  541.                     ENDIF
  542.                 ENDIF
  543.                 deb_morceau:=pointeur_car
  544.             ENDIF
  545.         ELSE
  546.             IF (Char(pointeur_car)="'") AND ((Char(pointeur_car-1)<>34) OR ((pointeur_car-1)<chaine_avant))
  547.                 INC pointeur_car
  548.                 WHILE (pointeur_car<fin_chaine_avant) AND (Char(pointeur_car)<>"'") DO INC pointeur_car
  549.             ENDIF
  550.             INC pointeur_car
  551.         ENDIF
  552.     ENDWHILE
  553.     IF long_temp:=(pointeur_car-deb_morceau)
  554.         morceaux:=Link(List(LONG_MORCEAU_CORPS),morceaux)
  555.         morceaux.macro:=FALSE
  556.         morceaux.ptr_texte:=deb_morceau
  557.         morceaux.longueur:=long_temp
  558.         long_chaine_apres:=long_chaine_apres+morceaux.longueur
  559.     ENDIF
  560.     morceaux_temp:=NIL
  561.     WHILE morceaux
  562.         morceau:=morceaux
  563.         morceaux:=Next(morceaux)
  564.         morceaux_temp:=Link(morceau,morceaux_temp)
  565.         IF morceau.macro
  566.             ptr_macro:=morceau.ptr_macro
  567.             pre_analyser_macro(ptr_macro,verbose)
  568.             IF ptr_macro.nbre_args
  569.                 parametres:=morceau.parametres
  570.                 FOR i:=0 TO ptr_macro.nbre_args-1 DO parametres[i]:=traiter_chaine(parametres[i],verbose)
  571.                 morceau.chaine_traite:=traiter_corps_macro(ptr_macro,parametres)
  572.             ELSE
  573.                 morceau.chaine_traite:=String(EstrLen(ptr_macro.corps))
  574.                 StrCopy(morceau.chaine_traite,ptr_macro.corps,ALL)
  575.             ENDIF
  576.             long_chaine_apres:=long_chaine_apres+EstrLen(morceau.chaine_traite)
  577.         ENDIF
  578.     ENDWHILE
  579.     chaine_apres:=String(long_chaine_apres)
  580.     morceaux:=morceaux_temp
  581.     WHILE morceaux
  582.         IF morceaux.macro THEN StrAdd(chaine_apres,morceaux.chaine_traite,ALL) ELSE StrAdd(chaine_apres,morceaux.ptr_texte,morceaux.longueur)
  583.         morceaux:=Next(morceaux)
  584.     ENDWHILE
  585. ENDPROC chaine_apres
  586. /*EF*/
  587.  
  588.  
  589. /****************************************************************************************/
  590. /* Retourne un pointeur sur le descriptif de la macro dont le nom est passe en argument */
  591. /****************************************************************************************/
  592. PROC est_ce_macro(nom_macro:PTR TO CHAR,hash_code)
  593. /*SF*/
  594.     DEF liste_macros_hash:PTR TO def_macro
  595.  
  596.     liste_macros_hash:=table_macros[hash_code].liste_macros
  597.     WHILE liste_macros_hash
  598.         IF StrCmp(liste_macros_hash.nom,nom_macro,ALL)
  599.             RETURN liste_macros_hash
  600.         ELSE
  601.             liste_macros_hash:=Next(liste_macros_hash)
  602.         ENDIF
  603.     ENDWHILE
  604. ENDPROC NIL 
  605. /*EF*/
  606.  
  607. /*******************************************************/
  608. /* Retourne un tableau des arguments passes a la macro */
  609. /*******************************************************/
  610. PROC recuperer_args_macro(pointeur_car:PTR TO CHAR,fin_chaine,ptr_macro:PTR TO def_macro,parametres:PTR TO LONG)
  611. /*SF*/
  612.     DEF car,encore=TRUE,level=0
  613.     DEF deb_arg,long_arg,num_arg
  614.  
  615.     num_arg:=ptr_macro.nbre_args-1
  616.     IF pointeur_car<fin_chaine
  617.         IF (car:=Char(pointeur_car++))="("
  618.             deb_arg:=pointeur_car
  619.             WHILE (pointeur_car<fin_chaine) AND encore
  620.                 car:=Char(pointeur_car++)
  621.                 SELECT car
  622.                     CASE 34
  623.                         pointeur_car:=pointeur_car+2
  624.                     CASE ","
  625.                         IF level=0
  626.                             long_arg:=pointeur_car-deb_arg-1
  627.                             parametres[num_arg]:=String(long_arg)
  628.                             StrCopy(parametres[num_arg],deb_arg,long_arg)
  629.                             DEC num_arg
  630.                             deb_arg:=pointeur_car
  631.                             IF num_arg<0
  632.                                 Vprintf('Wrong number of args in \s call !\n',[ptr_macro.nom])
  633.                                 Raise(WRONG_MACRO_USE)
  634.                             ENDIF
  635.                         ENDIF
  636.                     CASE "("
  637.                         INC level
  638.                     CASE ")"
  639.                         IF level
  640.                             DEC level
  641.                         ELSE
  642.                             long_arg:=pointeur_car-deb_arg-1
  643.                             parametres[num_arg]:=String(long_arg)
  644.                             StrCopy(parametres[num_arg],deb_arg,long_arg)
  645.                             DEC num_arg
  646.                             encore:=FALSE
  647.                         ENDIF
  648.                     CASE "'"
  649.                         WHILE (pointeur_car<fin_chaine) AND (Char(pointeur_car)<>"'") DO INC pointeur_car
  650.                         INC pointeur_car
  651.                 ENDSELECT
  652.             ENDWHILE
  653.             IF encore
  654.                 Vprintf('Unexpected end of macro body in the middle of \s call !\n',[ptr_macro.nom])
  655.                 Raise(WRONG_MACRO_USE)
  656.             ENDIF
  657.         ELSE
  658.             DEC pointeur_car
  659.             IF car=10 THEN DEC num_ligne
  660.         ENDIF
  661.     ENDIF
  662.     IF num_arg>=0
  663.         Vprintf('Wrong number of args in \s call !\n',[ptr_macro.nom])
  664.         Raise(WRONG_MACRO_USE)
  665.     ENDIF
  666. ENDPROC pointeur_car
  667. /*EF*/
  668.  
  669. /*************************************************************/
  670. /* Retourne le corps de la macro en remplacant les arguments */
  671. /*************************************************************/
  672. PROC traiter_corps_macro(ptr_macro:PTR TO def_macro,parametres:PTR TO LONG)
  673. /*SF*/
  674.     DEF long_corps,long_corps_temp,long_args:PTR TO LONG
  675.     DEF corps_macro_expandee,car,pos:PTR TO CHAR,i
  676.  
  677.     long_args:=List(ptr_macro.nbre_args)
  678.     FOR i:=0 TO ptr_macro.nbre_args-1 DO long_args[i]:=EstrLen(parametres[i])
  679.     long_corps:=EstrLen(ptr_macro.corps)
  680.     long_corps_temp:=long_corps
  681.     pos:=ptr_macro.corps
  682.     FOR i:=0 TO long_corps_temp-1 DO IF (car:=pos[i])>=128 THEN long_corps:=long_corps+long_args[car-128]-1
  683.     corps_macro_expandee:=String(long_corps)
  684.     pos:=ptr_macro.corps
  685.     FOR i:=0 TO long_corps_temp-1 DO  IF (car:=pos[i])>=128 THEN StrAdd(corps_macro_expandee,parametres[car-128],ALL) ELSE StrAdd(corps_macro_expandee,(pos+i),1)
  686. ENDPROC corps_macro_expandee
  687. /*EF*/
  688.  
  689. /*******************************************/
  690. /* Sauvegarde le fichier de macros analyse */
  691. /*******************************************/
  692. PROC ecrire_fichier_macros_analyse(nom_fichier:PTR TO CHAR)
  693. /*SF*/
  694.     DEF fichier,liste_macros_hash:PTR TO def_macro
  695.     DEF quotient,i
  696.  
  697.     fichier:=Open(nom_fichier,NEWFILE)
  698.     Fputs(fichier,'PreMac2E_Save_Format_V1.0')
  699.     FputC(fichier,0)
  700.  
  701.     FOR i:=0 TO 255
  702.         quotient:=table_macros[i].nbre_macros/256
  703.         FputC(fichier,quotient)
  704.         FputC(fichier,table_macros[i].nbre_macros-(quotient*256))
  705.         liste_macros_hash:=table_macros[i].liste_macros
  706.         WHILE liste_macros_hash
  707.             FputC(fichier,EstrLen(liste_macros_hash.nom))
  708.             Fputs(fichier,liste_macros_hash.nom)
  709.             FputC(fichier,0)
  710.             FputC(fichier,liste_macros_hash.nbre_args)
  711.             quotient:=EstrLen(liste_macros_hash.corps)/256
  712.             FputC(fichier,quotient)
  713.             FputC(fichier,EstrLen(liste_macros_hash.corps)-(quotient*256))
  714.             Fputs(fichier,liste_macros_hash.corps)
  715.             FputC(fichier,0)
  716.             liste_macros_hash:=Next(liste_macros_hash)
  717.         ENDWHILE
  718.     ENDFOR
  719.  
  720.     Close(fichier)
  721. ENDPROC
  722. /*EF*/
  723.  
  724.  
  725.